// © 2009 Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.Security.Permissions;
using System.Threading;

using Microsoft.InformationSecurity.ISRM.TaskManagment.Classes;
using Microsoft.InformationSecurity.CISF.Security;

namespace Microsoft.InformationSecurity.ISRM.TaskManagment.WebService
{
    /// <summary>
    /// Service implementation for the tasks service WCF interface.
    /// </summary>
    public class TasksService : ITasksService
    {
        const string eventSource = "Risk Tracker";
        const string logName = "Risk Service";   

        #region ITasksService Members

        /// <summary>
        /// Returns list of all tasks for specified risk identifier,
        /// </summary>
        /// <param name="riskID">Risk Identifier</param>
        /// <returns>List of Tasks</returns>
        public ICollection<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Task> GetTasks(int riskID)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task User", true);
                permission.Demand();

                return Tasks.GetTasks(riskID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        /// <summary>
        /// Returns list of all tasks for specifiied user and risk identifier.
        /// </summary>
        /// <param name="riskID">Risk Identifier</param>
        /// <param name="userID">User Identifier</param>
        /// <returns>List of Tasks</returns>
        public ICollection<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Task> GetTasksByUser(int riskID, int userID)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task User", true);
                permission.Demand();

                return Tasks.GetTasksByUser(riskID, userID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        
        /// <summary>
        /// Adds list of tasks to the database.
        /// </summary>
        /// <param name="tasks">List of Tasks</param>
        /// <returns>List of Tasks</returns>
        public List<Task> AddTasks(List<Task> tasks) 
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Trusted Task User", true);
                permission.Demand();

                return new List<Task>(Tasks.AddTasks(tasks));
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        
        /// <summary>
        /// Updates an existing task in the database.
        /// </summary>
        /// <param name="task">Updated Task</param>
        public void UpdateTask(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Task task)
        {
            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task User", true);
                permission.Demand();

                Tasks.UpdateTask(task);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

       
        /// <summary>
        /// Returns a task for the specified task identifier.
        /// </summary>
        /// <param name="taskID">Task Identifier</param>
        /// <returns>Task</returns>
        public Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Task GetTask(int taskID)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task User", true);
                permission.Demand();

                return Tasks.GetTask(taskID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        
        /// <summary>
        /// Adds a new category to the database.
        /// </summary>
        /// <param name="category">New Category</param>
        /// <returns>Category Identifier</returns>
        public int AddCategory(Category category)
        {
            int categoryID = -1;
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                categoryID = Categories.AddCategory(category);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }               
            return categoryID;
        }

        /// <summary>
        /// Updates an existing category in the database.
        /// </summary>
        /// <param name="category">Existing category</param>
        public void UpdateCategory(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Category category)
        {          
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Categories.UpdateCategory(category);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }        
        }

        /// <summary>
        /// Deletes an existing category in the database.
        /// </summary>
        /// <param name="category">Existing Category</param>
        public void DeleteCategory(Category category)
        {          
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Categories.DeleteCategory(category.ID, category.LastUpdatedBy, category.PersonID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }            
        }

        /// <summary>
        /// Returns list of all categories.
        /// </summary>
        /// <returns>List of Categories</returns>
        public ICollection<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Category> GetAllCategories()
        {
            try
            {
            return Categories.GetAllCategories();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Returns list of all active categories.
        /// </summary>
        /// <returns>List of Categories</returns>
        public ICollection<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Category> GetActiveCategories()
        {
            ICollection<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.Category> activeGroups = null;
            try
            {                
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;

                if (principal.IsInRole("Task User") || principal.IsInRole("Task Admin"))
                    activeGroups = Categories.GetActiveCategories();
                else
                    throw new System.Security.SecurityException("Permission denied.");

            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }
            return activeGroups;                             
        }

        /// <summary>
        /// Adds a new group to the database.
        /// </summary>
        /// <param name="group">New group</param>
        /// <returns>Group Identifier</returns>
        public int AddGroup(Group group)
        {
            int groupID = -1;
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                groupID = Groups.AddGroup(group);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }
            return groupID;
        }

        /// <summary>
        /// Updates an existing group in the database.
        /// </summary>
        /// <param name="group">Existing group</param>
        public void UpdateGroup(Group group)
        {
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Groups.UpdateGroup(group);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }               
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Deletes an existing group in the database.
        /// </summary>
        /// <param name="group">Existing Group</param>
        public void DeleteGroup(Group group)
        {          
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Groups.DeleteGroup(group.ID, group.LastUpdatedBy, group.PersonID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Returns list of all groups.
        /// </summary>
        /// <returns>List of Groups</returns>
        public ICollection<Group> GetAllGroups()
        {
            try
            {
                return Groups.GetAllGroups();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// Returns list of active groups.
        /// </summary>
        /// <returns>List of Groups</returns>
        public ICollection<Group> GetActiveGroups()
        {
            ICollection<Group> activeGroups = null;
            try
            {                
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;

                if (principal.IsInRole("Task User") || principal.IsInRole("Task Admin"))
                    activeGroups = Groups.GetActiveGroups();
                else
                    throw new System.Security.SecurityException("Permission denied.");
                
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            catch
            {
                throw;
            }
            return activeGroups;
        }

        /// <summary>
        /// Returns the number of tasks by the specified filter.
        /// </summary>
        /// <param name="field">Filter Field</param>
        /// <param name="soperator">Field Operator</param>
        /// <param name="values">Values</param>
        /// <param name="isTaskUser">Task User Only</param>
        /// <param name="personID">User Identifier</param>
        /// <param name="isActiveTasksOnly">Active Tasks Only</param>
        /// <returns>Number of Tasks</returns>
        public int GetTasksCountByFilter(string field, string soperator, string[] values, bool isTaskUser, int personID, bool isActiveTasksOnly) 
        {            
            int result = 0;
            try
            {
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;

                if (principal.IsInRole("Task User"))
                    result = Tasks.GetTasksCountByFilter(field, soperator, values, isTaskUser, personID, isActiveTasksOnly);
                else
                    throw new System.Security.SecurityException("Permission denied.");

            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            return result;
        }

        /// <summary>
        /// Returns the list of tasks by the specified filter.
        /// </summary>
        /// <param name="field">Filter Field</param>
        /// <param name="soperator">Field Operator</param>
        /// <param name="values">Values</param>
        /// <param name="isTaskUser">Task User Only</param>
        /// <param name="personID">User Identifier</param>
        /// <param name="isActiveTasksOnly">Active Tasks Only</param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="sortDescending">Sorts by descending order</param>
        /// <param name="sortField">Field to sort the results by</param>
        /// <param name="startRowIndex">Start row index</param>
        /// <returns></returns>
        public ICollection<Task> GetTasksByFilter(string field, string soperator, string[] values, string sortField, bool sortDescending, int pageSize, int startRowIndex, bool isTaskUser, int personID, bool isActiveTasksOnly)
        {            
            ICollection<Task> taskCollection = null;
            try
            {
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;

                if (principal.IsInRole("Task User"))
                    taskCollection = Tasks.GetTasksByFilter(field, soperator, values, sortField, sortDescending, pageSize, startRowIndex, isTaskUser, personID, isActiveTasksOnly);
                else
                    throw new System.Security.SecurityException("Permission denied.");

            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
            return taskCollection;
        }

        /// <summary>
        /// Returns all status for tasks.
        /// </summary>
        /// <returns>List of Status</returns>
        public ICollection<TaskStatus> GetAllTaskStatus()
        {
            return Tasks.GetAllTaskStatus();
        }

        /// <summary>
        /// Returns list of all task users.
        /// </summary>
        /// <returns>List of Users</returns>
        public ICollection<User> GetTasksUsers()
        {
            return Tasks.GetTasksUsers();
        }

        /// <summary>
        /// Returns true if the user is a valid trusted task user for a specified risk identifier.
        /// </summary>
        /// <param name="taskid">Task identifier</param>
        /// <param name="userid">Risk identifier</param>
        /// <returns></returns>
        public bool IsValidTrustedTaskUser(int taskid, int userid) 
        {
            return Tasks.IsValidTrustedTaskUser(taskid, userid);
        }

        #endregion
    }
}
